import math
from PyQt4 import QtGui, QtOpenGL, QtCore, Qt

import picts

class AssetItem( QtGui.QGraphicsItemGroup ):
    SELECTION = set([])
    def __init__(self, owner, x, y, name ):
        self.size = 25
        self.upLinks = []
        self.downLinks = []
        self.name = name
        QtGui.QGraphicsItemGroup.__init__( self )
        self.setZValue( 1 )
        self.setPos( x,y )
        #self.setFlags(
        #    QtGui.QGraphicsItem.ItemIsSelectable
        #    | QtGui.QGraphicsItem.ItemIsMovable # dont use this, it is the default behavior only
        #)
        print 'ASSET FLAGS', self.flags()
        self.setToolTip("test")
        
        body = QtGui.QGraphicsEllipseItem( -self.size/2, -self.size/2, self.size, self.size, self)
        self.addToGroup( body )
        #body._mover = self
        body._selecter = self
        body.setFlags( QtGui.QGraphicsItem.ItemIsSelectable )
        body.setBrush( QtGui.QBrush( QtGui.QColor(92, 143, 174) ) )
        body.setPen(
            QtGui.QPen( 
                QtGui.QBrush(
                    QtGui.QColor(128, 255, 128) 
                ),
                5
            )
        )
        
        self.text = QtGui.QGraphicsSimpleTextItem( self.name+'\nTEST', self )
        self.addToGroup( self.text )
        #self.text._mover = self
        self.text._selecter = self
        br = self.text.boundingRect()
        self.text.setPos( -br.width()/2, self.size/2 )
        
        pix = QtGui.QGraphicsPixmapItem( QtGui.QPixmap(picts.random()), self )
        self.addToGroup( pix )
        #pix._mover = self
        pix._selecter = self
        w = pix.boundingRect().width()
        pix.setPos( -w/2, -w/2 )
    
    def __del__( self ):
        if self in AssetItem.SELECTION:
            AssetItem.SELECTION.remove(self)
    
    def GetMovables( self, mode ):
        '''
        Called by the move manipulator.
        
        mode:
            0 -> normal
            1 -> ups
            2 -> downs
        '''
        ret = [self]
        if mode == 1:
            ret.extend( self.GetUps(True) )
        elif mode == 2:
            ret.extend( self.GetDowns(True) )
        return set(ret)
    
    def AddUpLink( self, link ):
        self.upLinks.append( link )
    
    def AddDownLink( self, link ):
        self.downLinks.append( link )
    
    def GetUps( self, recurs=False ):
        ret = [ l.src for l in self.upLinks ]
        if recurs:
            [ret.extend(u.GetUps(True)) for u in ret]
        return ret
        
    def GetDowns( self, recurs=False ):
        ret = [ l.dst for l in self.downLinks ]
        if recurs:
            [ret.extend(d.GetDowns(True)) for d in ret]
        return ret
    
    def GetLinkOutPoint( self ):
        return QtCore.QPointF( self.size/2,0 )
    
    def GetLinkInPoint( self ):
        return QtCore.QPointF( -self.size/2,0 )
    
    def itemChange( self, change, value ):
        if change == QtGui.QGraphicsItem.ItemPositionHasChanged:
            [ link.Adjust() for link in self.upLinks ]
            [ link.Adjust() for link in self.downLinks ]
        return QtGui.QGraphicsItemGroup.itemChange( self, change, value )
    
    def contextMenuEvent( self, event ):
        view = event.widget()
        menu = QtGui.QMenu(view)
        a = menu.addAction( self.name+" Action A")
        b = menu.addAction( self.name+" Action B")
        action = menu.exec_(QtGui.QCursor().pos())
        if action == a:
            print 'Action A'
        elif action == b:
            print 'Action B'
    
    def setSelected( self, b ):
        if b:
            AssetItem.SELECTION.add(self)
        elif self in AssetItem.SELECTION:
            AssetItem.SELECTION.remove(self)
        
        self._selected = b
        if b:
            self.text.setBrush( QtGui.QBrush( QtGui.QColor(128, 64, 64) ) )
        else:
            self.text.setBrush( QtGui.QBrush( QtGui.QColor(0, 0, 0) ) )
    
    def toggleSelected(self):
        self.setSelected( not self._selected )
    
    @classmethod
    def clearSelect( cls ):
        items = list(cls.SELECTION)
        [ i.setSelected(False) for i in items ]
        cls.SELECTION = set([])
    
    @classmethod
    def getSelected( cls ):
        return cls.SELECTION
    
Pi = math.pi
TwoPi = 2.0 * Pi

class LinkItem( QtGui.QGraphicsItem ):
    def __init__( self, src, dst, ltype ):
        QtGui.QGraphicsItem.__init__( self )
        print 'LINK FLAGS', self.flags()
        self.setZValue( -1 )
        self.src = src
        self.dst = dst
        self.path = QtGui.QPainterPath()
        self.ltype = ltype
        if ltype == 1:
            self.color = QtGui.QColor(255, 255, 136)
        else:
            self.color = QtGui.QColor(136, 255, 255)
        self.dcolor = self.color
        self.arrowSize = 10
        src.AddDownLink( self )
        dst.AddUpLink( self )
        self.Adjust()

    def Adjust(self):
        if not self.src or not self.dst:
            return
        
        if 0:
            line = QtCore.QLineF(
                self.mapFromItem( self.src, self.src.GetLinkOutPoint() ),
                self.mapFromItem( self.dst, self.dst.GetLinkInPoint() )
            )
            length = line.length()
            
            self.prepareGeometryChange()
            
            if length > 20:
                srcEdgeOffset = QtCore.QPointF(
                    ( line.dx() * self.src.size/2 ) / length, 
                    ( line.dy() * self.src.size/2 ) / length
                )
                sourcePoint = line.p1() + srcEdgeOffset
                destPoint = line.p2()
            else:
                sourcePoint = destPoint = line.p1()
        else:
            self.prepareGeometryChange()
            sourcePoint = self.mapFromItem( self.src, self.src.GetLinkOutPoint() )
            destPoint = self.mapFromItem( self.dst, self.src.GetLinkInPoint() )
        
        self.path = QtGui.QPainterPath()
        self.path.moveTo(sourcePoint)
        self.path.cubicTo(
            sourcePoint + QtCore.QPointF(100,0),
            destPoint - QtCore.QPointF(100,0),
            destPoint
        )
        self.dcolor = destPoint.x() > sourcePoint.x() and self.color or QtCore.Qt.red
    
    def boundingRect(self):
        return self.path.boundingRect().adjusted( -3, -3, 3, 3 )
    
    def paint( self, painter, styleOption, w ):
        if not self.src or not self.dst:
            return
        
        # draw antialiased:
        painter.setRenderHints(
            QtGui.QPainter.Antialiasing | 
            QtGui.QPainter.SmoothPixmapTransform
        )
        # Draw the line itself
        painter.setPen(
            QtGui.QPen( 
                self.dcolor, 1, 
                QtCore.Qt.SolidLine, 
                QtCore.Qt.RoundCap, 
                QtCore.Qt.RoundJoin
            )
        )
        #painter.drawLine(line)
        if self.path is not None:
            painter.drawPath(self.path)
        
        return 
        # Draw the arrows
        angle = math.acos( line.dx() / line.length() )
        if line.dy() >= 0:
            angle = TwoPi - angle
        
        destArrowP1 = self.destPoint + QtCore.QPointF(
            math.sin(angle-Pi/3) * self.arrowSize,
            math.cos(angle-Pi/3) * self.arrowSize
        )
        destArrowP2 = self.destPoint + QtCore.QPointF(
            math.sin(angle-Pi+Pi/3) * self.arrowSize,
            math.cos(angle - Pi + Pi / 3) * self.arrowSize
        )

        painter.setBrush(color)
        poly = QtGui.QPolygonF()
        poly.append(line.p2())
        poly.append(destArrowP1)
        poly.append(destArrowP2)
        painter.drawPolygon( poly )


class Scene( QtGui.QGraphicsScene ):
    def __init__( self ):
        QtGui.QGraphicsScene.__init__( self )
        self._root = None
    
    def root( self ):
        return self._root
    
    def setRoot( self, item ):
        self._root = item
        QtGui.QGraphicsScene.addItem( self, item )
    
    def addItem( self, item ):
        item.setParentItem( self._root )
    
    def sceneRect( self ):
        if self.root():
            print self._root.sceneBoundingRect()
            return self._root.sceneBoundingRect()
        return QtGui.QGraphicsScene.sceneRect( self )
    
